<template>
  <div class="login-container">
    <el-form class="login-form layui-anim layui-anim-scale" ref="loginForm" :model="loginForm" :rules="loginRules">
      <div class="title-container">
        <img src="@/assets/images/login-logo.png" alt="logo">
      </div>
      <el-form-item prop="mobile">
        <span class="svg-container">
          <svg-icon icon-class="user"/>
        </span>
        <el-input placeholder="请输入手机号" ref="username" v-model.trim="loginForm.mobile"/>
      </el-form-item>
      <el-form-item prop="password">
        <span class="svg-container">
          <svg-icon icon-class="password"/>
        </span>
        <el-input :type="passwordType" placeholder="请输入密码" :key="passwordType" ref="password" v-model.trim="loginForm.password" @keyup.enter.native="handleLogin"/>
        <span class="show-pwd" @click="handleShowPwd">
          <svg-icon :icon-class="showPasswordType"/>
        </span>
      </el-form-item>
      <el-button :loading="loading" type="primary" @click.native.prevent="handleLogin">登录</el-button>
    </el-form>
  </div>
</template>

<script>
import { validMobile } from '@/utils/validate'

export default {
  name: 'Login',
  data() {
    /* 自定义校验手机号的回调函数*/
    const validateMobile = (rule, value, callback) => {
      /* rule:规则对象
       * value:校验的数据值
       * callback:决定是否通过的函数
       */
      if (!value.length) return callback(new Error('请输入手机号'))
      if (!validMobile(value)) return callback(new Error('手机号格式不正确'))
      callback()
    }
    /* 自定义校验密码的回调函数 */
    const validatePassword = (rule, value, callback) => {
      /* rule:规则对象
      *  value:校验的数据值
      *  callback:决定是否通过的函数
      */
      if (!value.length) return callback(new Error('请输入密码'))
      callback()
    }
    return {
      /* 表单数据对象 */
      loginForm: {
        mobile: process.env.NODE_ENV === 'development' ? '13800000002' : '',
        password: process.env.NODE_ENV === 'development' ? 'hm#qd@23!' : ''
      },
      /* 表单规则对象 */
      loginRules: {
        /*required字段:必填项 trigger字段:事件触发校验 validator字段:自定义校验函数 pattern字段:正则表达式 message字段:提示信息 max字段:最大长度 min字段:最小长度*/
        mobile: [{ validator: validateMobile, trigger: 'blur' }],
        password: [{ validator: validatePassword, trigger: 'blur' }]
      },
      /* 按钮的loading状态 */
      loading: false,
      /* 密码框的类型 */
      passwordType: 'password',
      /* 重定向的URL路径 */
      redirect: undefined
    }
  },
  watch: {
    /* 监听路由参数对象 $route的变化 */
    $route: {
      // 执行函数
      handler(route) {
        this.redirect = route.query && route.query.redirect
      },
      // 开启立即监听
      immediate: true
    }
  },
  methods: {
    /* 点击密码框小眼睛的回调函数(用于显示和隐藏密码) */
    handleShowPwd() {
      this.passwordType = this.passwordType === 'password' ? '' : 'password'
      this.$nextTick(() => {
        this.$refs.password.focus()
      })
    },
    /* 点击登录按钮的回调函数 */
    async handleLogin() {
      /*
      * 1.进行表单的兜底校验，表单兜底校验不通过则return出去不执行逻辑，校验通过派发一个action携带表单的用户名和密码去发送登录请求
      * 2.action如果+了async修饰符返回的是一个Promise对象，组件里使用try-catch捕获本次发送登录请求出现的错误(请求失败在响应拦截器中做了处理会return一个失败的Promise对象)
      * 3.发送登录请求成功了跳转首页，失败提示用户本次登录失败并且告知原因
      * validate(callback:Function(boolean, object))对整个表单进行校验的方法，参数为回调函数。
      * 该回调函数会在校验结束后被调用，并传入两个参数：是否校验成功和未通过校验的字段。(若不传入回调函数则会返回一个promise!!!)
      * */
      // 进行表单的兜底校验(返回true成功，false则失败)
      const valid = await this.$refs.loginForm.validate().catch(error => error)
      // 判断validate()函数返回的布尔值结果(如果为false则return出去不执行下面的逻辑)
      if (!valid) return this.$message.warning('请完善您的登录信息')
      // 开启按钮loading效果
      this.loading = true
      try {
        // 派发一个action去发送登录请求(返回Promise对象)
        const message = await this.$store.dispatch('user/loginAction', this.loginForm)
        // 提示用户登录成功
        this.$message.success(message)
        // 跳转首页||this.redirect
        this.$router.push(this.redirect || '/')
      } catch (error) {
        // 本次派发action登录请求-失败
        // 提示用户失败的原因
        this.$message.error(error.message)
      } finally {
        // 成功和失败都会执行-关闭按钮loading效果
        this.loading = false
      }
    }
  },
  computed: {
    showPasswordType() {
      return this.passwordType === 'password' ? 'eye' : 'eye-open'
    }
  }
}
</script>

<style lang="scss">
$bg: #283443;
$light_gray: #68b0fe;
$cursor: #fff;

@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
  .login-container .el-input input {
    color: $cursor;
  }
}

.login-container {
  .el-input {
    display: inline-block;
    height: 47px;
    width: 85%;

    input {
      background: transparent;
      border: 0;
      -webkit-appearance: none;
      border-radius: 0;
      padding: 12px 5px 12px 15px;
      color: $light_gray;
      height: 60px;
      caret-color: #fff;


      &::placeholder {
        color: #b0b0b0;
      }
    }
  }

  .el-form-item {
    border: 1px solid rgba(255, 255, 255, .8);
    background: rgba(255, 255, 255, .8);
    border-radius: 5px;

    .el-form-item__error {
      color: #ff5047;
    }
  }
}
</style>

<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: #889aa4;
$light_gray: #eee;

.login-container {
  min-height: 100%;
  width: 100%;
  background: url("~@/assets/images/login.jpg") center center;
  background-size: cover;
  overflow: hidden;

  .title-container {
    text-align: center;
    margin-bottom: 50px;

    img {
      width: 100%;
    }
  }

  .login-form {
    position: relative;
    width: 550px;
    max-width: 100%;
    padding: 160px 35px 0;
    margin: 0 auto;
    overflow: hidden;
  }


  .svg-container {
    padding: 1px 5px 6px 15px;
    color: $dark_gray;
    vertical-align: middle;
    width: 30px;
    display: inline-block;
  }

  .show-pwd {
    position: absolute;
    right: 10px;
    top: 7px;
    font-size: 16px;
    color: $dark_gray;
    cursor: pointer;
    user-select: none;
  }

  .el-button {
    width: 100%;
    height: 65px;
    font-size: 24px;
    margin-bottom: 10px;
    background-color: #407ffe;
    border: 0;

    &:hover {
      background-color: #3d77ea;

    }
  }
}
</style>
